home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 4_0 / FLEX-TC_ / SCAN.L < prev    next >
Text File  |  1990-01-02  |  11KB  |  437 lines

  1. /* scan.l - scanner for flex input */
  2.  
  3. /*
  4.  * Copyright (c) 1989 The Regents of the University of California.
  5.  * All rights reserved.
  6.  *
  7.  * This code is derived from software contributed to Berkeley by
  8.  * Vern Paxson.
  9.  * 
  10.  * The United States Government has rights in this work pursuant to
  11.  * contract no. DE-AC03-76SF00098 between the United States Department of
  12.  * Energy and the University of California.
  13.  *
  14.  * Redistribution and use in source and binary forms are permitted
  15.  * provided that the above copyright notice and this paragraph are
  16.  * duplicated in all such forms and that any documentation,
  17.  * advertising materials, and other materials related to such
  18.  * distribution and use acknowledge that the software was developed
  19.  * by the University of California, Berkeley.  The name of the
  20.  * University may not be used to endorse or promote products derived
  21.  * from this software without specific prior written permission.
  22.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  23.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  24.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  25.  */
  26.  
  27. %{
  28. #include "flexdef.h"
  29. #include "parse.h"
  30.  
  31. #ifndef lint
  32. static char copyright[] =
  33.     "@(#) Copyright (c) 1989 The Regents of the University of California.\n";
  34. static char CR_continuation[] = "@(#) All rights reserved.\n";
  35.  
  36. static char rcsid[] =
  37.     "@(#) $Header: scan.l,v 2.1 89/06/20 17:24:13 vern Exp $ (LBL)";
  38. #endif
  39.  
  40. #define ACTION_ECHO fprintf( temp_action_file, "%s", yytext )
  41. #define MARK_END_OF_PROLOG fprintf( temp_action_file, "%%%% end of prolog\n" );
  42.  
  43. #undef YY_DECL
  44. #define YY_DECL \
  45.     int flexscan()
  46.  
  47. #define RETURNCHAR \
  48.     yylval = yytext[0]; \
  49.     return ( CHAR );
  50.  
  51. #define RETURNNAME \
  52.     (void) strcpy( nmstr, yytext ); \
  53.     return ( NAME );
  54.  
  55. #define PUT_BACK_STRING(str, start) \
  56.     for ( i = strlen( str ) - 1; i >= start; --i ) \
  57.         unput(str[i])
  58.  
  59. #define CHECK_REJECT(str) \
  60.     if ( all_upper( str ) ) \
  61.         reject = true;
  62.  
  63. #define CHECK_YYMORE(str) \
  64.     if ( all_lower( str ) ) \
  65.         yymore_used = true;
  66. %}
  67.  
  68. %x SECT2 SECT2PROLOG SECT3 CODEBLOCK PICKUPDEF SC CARETISBOL NUM QUOTE
  69. %x FIRSTCCL CCL ACTION RECOVER BRACEERROR C_COMMENT C_COMMENT_2 ACTION_COMMENT
  70. %x ACTION_STRING PERCENT_BRACE_ACTION USED_LIST
  71.  
  72. WS        [ \t\f]+
  73. OPTWS        [ \t\f]*
  74. NOT_WS        [^ \t\f\n]
  75.  
  76. NAME        [a-z_][a-z_0-9-]*
  77. NOT_NAME    [^a-z_\n]+
  78.  
  79. SCNAME        {NAME}
  80.  
  81. ESCSEQ        \\([^\n]|[0-9]{1,3})
  82.  
  83. %%
  84.     static int bracelevel, didadef;
  85.     int i, indented_code, checking_used;
  86.     char nmdef[MAXLINE], myesc();
  87.  
  88. ^{WS}            indented_code = true; BEGIN(CODEBLOCK);
  89. ^#.*\n            ++linenum; ECHO; /* treat as a comment */
  90. ^"/*"            ECHO; BEGIN(C_COMMENT);
  91. ^"%s"(tart)?        return ( SCDECL );
  92. ^"%x"            return ( XSCDECL );
  93. ^"%{".*\n        {
  94.             ++linenum;
  95.             line_directive_out( stdout );
  96.             indented_code = false;
  97.             BEGIN(CODEBLOCK);
  98.             }
  99.  
  100. {WS}            return ( WHITESPACE );
  101.  
  102. ^"%%".*            {
  103.             sectnum = 2;
  104.             line_directive_out( stdout );
  105.             BEGIN(SECT2PROLOG);
  106.             return ( SECTEND );
  107.             }
  108.  
  109. ^"%used"        checking_used = REALLY_USED; BEGIN(USED_LIST);
  110. ^"%unused"        checking_used = REALLY_NOT_USED; BEGIN(USED_LIST);
  111.  
  112.  
  113. ^"%"[^sx]" ".*\n        {
  114.             fprintf( stderr,
  115.                  "old-style lex command at line %d ignored:\n\t%s",
  116.                  linenum, yytext );
  117.             ++linenum;
  118.             }
  119.  
  120. ^{NAME}            {
  121.             (void) strcpy( nmstr, yytext );
  122.             didadef = false;
  123.             BEGIN(PICKUPDEF);
  124.             }
  125.  
  126. {SCNAME}        RETURNNAME;
  127. ^{OPTWS}\n        ++linenum; /* allows blank lines in section 1 */
  128. \n            ++linenum; return ( '\n' );
  129. .            synerr( "illegal character" ); BEGIN(RECOVER);
  130.  
  131.  
  132. <C_COMMENT>"*/"        ECHO; BEGIN(0);
  133. <C_COMMENT>"*/".*\n    ++linenum; ECHO; BEGIN(0);
  134. <C_COMMENT>[^*\n]+    ECHO;
  135. <C_COMMENT>"*"        ECHO;
  136. <C_COMMENT>\n        ++linenum; ECHO;
  137.  
  138.  
  139. <CODEBLOCK>^"%}".*\n    ++linenum; BEGIN(0);
  140. <CODEBLOCK>"reject"    ECHO; CHECK_REJECT(yytext);
  141. <CODEBLOCK>"yymore"    ECHO; CHECK_YYMORE(yytext);
  142. <CODEBLOCK>{NAME}|{NOT_NAME}|.    ECHO;
  143. <CODEBLOCK>\n        {
  144.             ++linenum;
  145.             ECHO;
  146.             if ( indented_code )
  147.                 BEGIN(0);
  148.             }
  149.  
  150.  
  151. <PICKUPDEF>{WS}        /* separates name and definition */
  152.  
  153. <PICKUPDEF>{NOT_WS}.*    {
  154.             (void) strcpy( nmdef, yytext );
  155.  
  156.             for ( i = strlen( nmdef ) - 1;
  157.                   i >= 0 &&
  158.                   nmdef[i] == ' ' || nmdef[i] == '\t';
  159.                   --i )
  160.                 ;
  161.  
  162.             nmdef[i + 1] = '\0';
  163.  
  164.                         ndinstal( nmstr, nmdef );
  165.             didadef = true;
  166.             }
  167.  
  168. <PICKUPDEF>\n        {
  169.             if ( ! didadef )
  170.                 synerr( "incomplete name definition" );
  171.             BEGIN(0);
  172.             ++linenum;
  173.             }
  174.  
  175. <RECOVER>.*\n        ++linenum; BEGIN(0); RETURNNAME;
  176.  
  177.  
  178. <USED_LIST>\n        ++linenum; BEGIN(0);
  179. <USED_LIST>{WS}
  180. <USED_LIST>"reject"    {
  181.             if ( all_upper( yytext ) )
  182.                 reject_really_used = checking_used;
  183.             else
  184.                 synerr( "unrecognized %used/%unused construct" );
  185.             }
  186. <USED_LIST>"yymore"    {
  187.             if ( all_lower( yytext ) )
  188.                 yymore_really_used = checking_used;
  189.             else
  190.                 synerr( "unrecognized %used/%unused construct" );
  191.             }
  192. <USED_LIST>{NOT_WS}+    synerr( "unrecognized %used/%unused construct" );
  193.  
  194.  
  195. <SECT2PROLOG>.*\n/{NOT_WS}    {
  196.             ++linenum;
  197.             ACTION_ECHO;
  198.             MARK_END_OF_PROLOG;
  199.             BEGIN(SECT2);
  200.             }
  201.  
  202. <SECT2PROLOG>.*\n    ++linenum; ACTION_ECHO;
  203.  
  204. <SECT2PROLOG><<EOF>>    MARK_END_OF_PROLOG; yyterminate();
  205.  
  206. <SECT2>^{OPTWS}\n    ++linenum; /* allow blank lines in section 2 */
  207.  
  208.     /* this horrible mess of a rule matches indented lines which
  209.      * do not contain "/*".  We need to make the distinction because
  210.      * otherwise this rule will be taken instead of the rule which
  211.      * matches the beginning of comments like this one
  212.      */
  213. <SECT2>^{WS}([^/\n]|"/"[^*\n])*("/"?)\n    {
  214.             synerr( "indented code found outside of action" );
  215.             ++linenum;
  216.             }
  217.  
  218. <SECT2>"<"        BEGIN(SC); return ( '<' );
  219. <SECT2>^"^"        return ( '^' );
  220. <SECT2>\"        BEGIN(QUOTE); return ( '"' );
  221. <SECT2>"{"/[0-9]        BEGIN(NUM); return ( '{' );
  222. <SECT2>"{"[^0-9\n][^}\n]*    BEGIN(BRACEERROR);
  223. <SECT2>"$"/[ \t\n]    return ( '$' );
  224.  
  225. <SECT2>{WS}"%{"        {
  226.             bracelevel = 1;
  227.             BEGIN(PERCENT_BRACE_ACTION);
  228.             return ( '\n' );
  229.             }
  230. <SECT2>{WS}"|".*\n    continued_action = true; ++linenum; return ( '\n' );
  231.  
  232. <SECT2>^{OPTWS}"/*"    ACTION_ECHO; BEGIN(C_COMMENT_2);
  233.  
  234. <SECT2>{WS}        {
  235.             /* this rule is separate from the one below because
  236.              * otherwise we get variable trailing context, so
  237.              * we can't build the scanner using -{f,F}
  238.              */
  239.             bracelevel = 0;
  240.             continued_action = false;
  241.             BEGIN(ACTION);
  242.             return ( '\n' );
  243.             }
  244.  
  245. <SECT2>{OPTWS}/\n    {
  246.             bracelevel = 0;
  247.             continued_action = false;
  248.             BEGIN(ACTION);
  249.             return ( '\n' );
  250.             }
  251.  
  252. <SECT2>^{OPTWS}\n    ++linenum; return ( '\n' );
  253.  
  254. <SECT2>"<<EOF>>"    return ( EOF_OP );
  255.  
  256. <SECT2>^"%%".*        {
  257.             sectnum = 3;
  258.             BEGIN(SECT3);
  259.             return ( EOF ); /* to stop the parser */
  260.             }
  261.  
  262. <SECT2>"["([^\\\]\n]|{ESCSEQ})+"]"    {
  263.             int cclval;
  264.  
  265.             (void) strcpy( nmstr, yytext );
  266.  
  267.             /* check to see if we've already encountered this ccl */
  268.             if ( (cclval = ccllookup( nmstr )) )
  269.                 {
  270.                 yylval = cclval;
  271.                 ++cclreuse;
  272.                 return ( PREVCCL );
  273.                 }
  274.             else
  275.                 {
  276.                 /* we fudge a bit.  We know that this ccl will
  277.                  * soon be numbered as lastccl + 1 by cclinit
  278.                  */
  279.                 cclinstal( nmstr, lastccl + 1 );
  280.  
  281.                 /* push back everything but the leading bracket
  282.                  * so the ccl can be rescanned
  283.                  */
  284.                 PUT_BACK_STRING(nmstr, 1);
  285.  
  286.                 BEGIN(FIRSTCCL);
  287.                 return ( '[' );
  288.                 }
  289.             }
  290.  
  291. <SECT2>"{"{NAME}"}"    {
  292.             register char *nmdefptr;
  293.             char *ndlookup();
  294.  
  295.             (void) strcpy( nmstr, yytext );
  296.             nmstr[yyleng - 1] = '\0';  /* chop trailing brace */
  297.  
  298.             /* lookup from "nmstr + 1" to chop leading brace */
  299.             if ( ! (nmdefptr = ndlookup( nmstr + 1 )) )
  300.                 synerr( "undefined {name}" );
  301.  
  302.             else
  303.                 { /* push back name surrounded by ()'s */
  304.                 unput(')');
  305.                 PUT_BACK_STRING(nmdefptr, 0);
  306.                 unput('(');
  307.                 }
  308.             }
  309.  
  310. <SECT2>[/|*+?.()]    return ( yytext[0] );
  311. <SECT2>.        RETURNCHAR;
  312. <SECT2>\n        ++linenum; return ( '\n' );
  313.  
  314.  
  315. <SC>","            return ( ',' );
  316. <SC>">"            BEGIN(SECT2); return ( '>' );
  317. <SC>">"/"^"        BEGIN(CARETISBOL); return ( '>' );
  318. <SC>{SCNAME}        RETURNNAME;
  319. <SC>.            synerr( "bad start condition name" );
  320.  
  321. <CARETISBOL>"^"        BEGIN(SECT2); return ( '^' );
  322.  
  323.  
  324. <QUOTE>[^"\n]        RETURNCHAR;
  325. <QUOTE>\"        BEGIN(SECT2); return ( '"' );
  326.  
  327. <QUOTE>\n        {
  328.             synerr( "missing quote" );
  329.             BEGIN(SECT2);
  330.             ++linenum;
  331.             return ( '"' );
  332.             }
  333.  
  334.  
  335. <FIRSTCCL>"^"/[^-\n]    BEGIN(CCL); return ( '^' );
  336. <FIRSTCCL>"^"/-        return ( '^' );
  337. <FIRSTCCL>-        BEGIN(CCL); yylval = '-'; return ( CHAR );
  338. <FIRSTCCL>.        BEGIN(CCL); RETURNCHAR;
  339.  
  340. <CCL>-/[^\]\n]        return ( '-' );
  341. <CCL>[^\]\n]        RETURNCHAR;
  342. <CCL>"]"        BEGIN(SECT2); return ( ']' );
  343.  
  344.  
  345. <NUM>[0-9]+        {
  346.             yylval = myctoi( yytext );
  347.             return ( NUMBER );
  348.             }
  349.  
  350. <NUM>","            return ( ',' );
  351. <NUM>"}"            BEGIN(SECT2); return ( '}' );
  352.  
  353. <NUM>.            {
  354.             synerr( "bad character inside {}'s" );
  355.             BEGIN(SECT2);
  356.             return ( '}' );
  357.             }
  358.  
  359. <NUM>\n            {
  360.             synerr( "missing }" );
  361.             BEGIN(SECT2);
  362.             ++linenum;
  363.             return ( '}' );
  364.             }
  365.  
  366.  
  367. <BRACEERROR>"}"        synerr( "bad name in {}'s" ); BEGIN(SECT2);
  368. <BRACEERROR>\n        synerr( "missing }" ); ++linenum; BEGIN(SECT2);
  369.  
  370.  
  371. <PERCENT_BRACE_ACTION>{OPTWS}"%}".*    bracelevel = 0;
  372. <PERCENT_BRACE_ACTION,ACTION>"reject"    ACTION_ECHO; CHECK_REJECT(yytext);
  373. <PERCENT_BRACE_ACTION,ACTION>"yymore"    ACTION_ECHO; CHECK_YYMORE(yytext);
  374. <PERCENT_BRACE_ACTION>{NAME}|{NOT_NAME}|.    ACTION_ECHO;
  375. <PERCENT_BRACE_ACTION>\n        {
  376.             ++linenum;
  377.             ACTION_ECHO;
  378.             if ( bracelevel == 0 )
  379.                 {
  380.                 fputs( "\tYY_BREAK\n", temp_action_file );
  381.                 BEGIN(SECT2);
  382.                 }
  383.             }
  384.  
  385.     /* REJECT and yymore() are checked for above, in PERCENT_BRACE_ACTION */
  386. <ACTION>"{"        ACTION_ECHO; ++bracelevel;
  387. <ACTION>"}"        ACTION_ECHO; --bracelevel;
  388. <ACTION>[^a-z_{}"'/\n]+    ACTION_ECHO;
  389. <ACTION>{NAME}        ACTION_ECHO;
  390. <ACTION>"/*"        ACTION_ECHO; BEGIN(ACTION_COMMENT);
  391. <ACTION>"'"([^'\\\n]|\\.)*"'"    ACTION_ECHO; /* character constant */
  392. <ACTION>\"        ACTION_ECHO; BEGIN(ACTION_STRING);
  393. <ACTION>\n        {
  394.             ++linenum;
  395.             ACTION_ECHO;
  396.             if ( bracelevel == 0 )
  397.                 {
  398.                 fputs( "\tYY_BREAK\n", temp_action_file );
  399.                 BEGIN(SECT2);
  400.                 }
  401.             }
  402. <ACTION>.        ACTION_ECHO;
  403.  
  404. <ACTION_COMMENT>"*/"    ACTION_ECHO; BEGIN(ACTION);
  405. <ACTION_COMMENT>[^*\n]+    ACTION_ECHO;
  406. <ACTION_COMMENT>"*"    ACTION_ECHO;
  407. <ACTION_COMMENT>\n    ++linenum; ACTION_ECHO;
  408. <ACTION_COMMENT>.    ACTION_ECHO;
  409.  
  410. <C_COMMENT_2>"*/"    ACTION_ECHO; BEGIN(SECT2);
  411. <C_COMMENT_2>"*/".*\n    ++linenum; ACTION_ECHO; BEGIN(SECT2);
  412. <C_COMMENT_2>[^*\n]+    ACTION_ECHO;
  413. <C_COMMENT_2>"*"    ACTION_ECHO;
  414. <C_COMMENT_2>\n        ++linenum; ACTION_ECHO;
  415.  
  416. <ACTION_STRING>[^"\\\n]+    ACTION_ECHO;
  417. <ACTION_STRING>\\.    ACTION_ECHO;
  418. <ACTION_STRING>\n    ++linenum; ACTION_ECHO;
  419. <ACTION_STRING>\"    ACTION_ECHO; BEGIN(ACTION);
  420. <ACTION_STRING>.    ACTION_ECHO;
  421.  
  422.  
  423. <SECT2,QUOTE,CCL>{ESCSEQ}    {
  424.             yylval = myesc( yytext );
  425.             return ( CHAR );
  426.             }
  427.  
  428. <FIRSTCCL>{ESCSEQ}    {
  429.             yylval = myesc( yytext );
  430.             BEGIN(CCL);
  431.             return ( CHAR );
  432.             }
  433.  
  434.  
  435. <SECT3>.*(\n?)        ECHO;
  436. %%
  437.